#!/bin/bash

# 系统监控脚本
set -e

# 配置
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
LOG_FILE="${PROJECT_DIR}/monitor.log"
ALERT_THRESHOLD_CPU=80
ALERT_THRESHOLD_MEMORY=80
ALERT_THRESHOLD_DISK=85

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    echo -e "$1" | tee -a "$LOG_FILE"
}

log_info() {
    log "${BLUE}[INFO $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

log_success() {
    log "${GREEN}[SUCCESS $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

log_warning() {
    log "${YELLOW}[WARNING $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

log_error() {
    log "${RED}[ERROR $(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}

# 加载环境变量
load_env() {
    if [ -f ".env.prod" ]; then
        source .env.prod
    else
        log_error "环境文件 .env.prod 不存在"
        exit 1
    fi
}

# 发送告警
send_alert() {
    local level=$1
    local message=$2
    
    log_warning "告警: $message"
    
    # 邮件通知
    if [ -n "$MONITOR_EMAIL" ] && command -v mail &> /dev/null; then
        echo "$message" | mail -s "系统告警 - $level" "$MONITOR_EMAIL"
    fi
    
    # Webhook通知
    if [ -n "$WEBHOOK_URL" ]; then
        curl -X POST "$WEBHOOK_URL" \
            -H "Content-Type: application/json" \
            -d "{\"level\":\"$level\",\"message\":\"$message\",\"timestamp\":\"$(date -Iseconds)\"}" \
            &> /dev/null || true
    fi
}

# 检查系统资源
check_system_resources() {
    log_info "检查系统资源使用情况..."
    
    # CPU使用率
    local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//')
    local cpu_percent=$(echo "$cpu_usage" | sed 's/[^0-9.]*//g')
    
    if (( $(echo "$cpu_percent > $ALERT_THRESHOLD_CPU" | bc -l) )); then
        send_alert "HIGH" "CPU使用率过高: ${cpu_percent}%"
    fi
    
    # 内存使用率
    local memory_info=$(free | grep Mem)
    local total_memory=$(echo $memory_info | awk '{print $2}')
    local used_memory=$(echo $memory_info | awk '{print $3}')
    local memory_percent=$(( used_memory * 100 / total_memory ))
    
    if [ $memory_percent -gt $ALERT_THRESHOLD_MEMORY ]; then
        send_alert "HIGH" "内存使用率过高: ${memory_percent}%"
    fi
    
    # 磁盘使用率
    local disk_usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
    
    if [ $disk_usage -gt $ALERT_THRESHOLD_DISK ]; then
        send_alert "HIGH" "磁盘使用率过高: ${disk_usage}%"
    fi
    
    log_info "系统资源检查完成 - CPU: ${cpu_percent}%, 内存: ${memory_percent}%, 磁盘: ${disk_usage}%"
}

# 检查Docker服务状态
check_docker_services() {
    log_info "检查Docker服务状态..."
    
    local services=("mongodb" "redis" "backend" "frontend" "nginx")
    local failed_services=()
    
    for service in "${services[@]}"; do
        local container_name="lesson-plan-${service}-prod"
        
        if docker ps --filter "name=${container_name}" --filter "status=running" | grep -q "$container_name"; then
            log_success "$service 服务运行正常"
        else
            log_error "$service 服务异常"
            failed_services+=("$service")
        fi
    done
    
    if [ ${#failed_services[@]} -gt 0 ]; then
        send_alert "CRITICAL" "Docker服务异常: ${failed_services[*]}"
        return 1
    fi
}

# 检查应用健康状态
check_application_health() {
    log_info "检查应用健康状态..."
    
    # 检查后端API
    if curl -f -s http://localhost:3001/health > /dev/null; then
        log_success "后端API健康检查通过"
    else
        log_error "后端API健康检查失败"
        send_alert "CRITICAL" "后端API服务不可用"
        return 1
    fi
    
    # 检查前端服务
    if curl -f -s http://localhost > /dev/null; then
        log_success "前端服务健康检查通过"
    else
        log_error "前端服务健康检查失败"
        send_alert "CRITICAL" "前端服务不可用"
        return 1
    fi
    
    # 检查数据库连接
    if docker-compose -f docker-compose.prod.yml exec -T mongodb mongo --eval "db.adminCommand('ping')" &> /dev/null; then
        log_success "数据库连接正常"
    else
        log_error "数据库连接失败"
        send_alert "CRITICAL" "数据库连接失败"
        return 1
    fi
}

# 检查日志错误
check_application_logs() {
    log_info "检查应用日志错误..."
    
    local error_count=$(docker-compose -f docker-compose.prod.yml logs --tail=100 backend 2>/dev/null | grep -i "error" | wc -l)
    
    if [ $error_count -gt 10 ]; then
        send_alert "MEDIUM" "后端服务出现大量错误: $error_count 条"
    fi
    
    # 检查数据库慢查询
    local slow_queries=$(docker-compose -f docker-compose.prod.yml exec -T mongodb mongo --eval "db.runCommand({profile: 0})" 2>/dev/null | grep -c "slow" || echo 0)
    
    if [ $slow_queries -gt 5 ]; then
        send_alert "MEDIUM" "数据库出现慢查询: $slow_queries 条"
    fi
}

# 检查证书到期时间
check_ssl_certificates() {
    if [ -f "docker/ssl/cert.pem" ]; then
        log_info "检查SSL证书..."
        
        local expiry_date=$(openssl x509 -enddate -noout -in docker/ssl/cert.pem | cut -d= -f2)
        local expiry_timestamp=$(date -d "$expiry_date" +%s)
        local current_timestamp=$(date +%s)
        local days_until_expiry=$(( (expiry_timestamp - current_timestamp) / 86400 ))
        
        if [ $days_until_expiry -lt 30 ]; then
            send_alert "MEDIUM" "SSL证书即将到期: $days_until_expiry 天"
        fi
        
        log_info "SSL证书还有 $days_until_expiry 天到期"
    fi
}

# 性能指标收集
collect_performance_metrics() {
    log_info "收集性能指标..."
    
    local timestamp=$(date -Iseconds)
    local metrics_file="${PROJECT_DIR}/metrics/$(date +%Y%m%d).json"
    
    mkdir -p "${PROJECT_DIR}/metrics"
    
    # 收集系统指标
    local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//' | sed 's/[^0-9.]*//g')
    local memory_info=$(free | grep Mem)
    local total_memory=$(echo $memory_info | awk '{print $2}')
    local used_memory=$(echo $memory_info | awk '{print $3}')
    local memory_percent=$(( used_memory * 100 / total_memory ))
    local disk_usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
    
    # 收集应用指标
    local response_time=$(curl -o /dev/null -s -w "%{time_total}" http://localhost:3001/health)
    
    # 保存为JSON格式
    cat >> "$metrics_file" << EOF
{
  "timestamp": "$timestamp",
  "system": {
    "cpu_percent": $cpu_usage,
    "memory_percent": $memory_percent,
    "disk_percent": $disk_usage
  },
  "application": {
    "response_time": $response_time
  }
},
EOF
    
    log_info "性能指标已保存: $metrics_file"
}

# 生成监控报告
generate_report() {
    log_info "生成监控报告..."
    
    local report_file="${PROJECT_DIR}/reports/monitor-report-$(date +%Y%m%d).html"
    mkdir -p "${PROJECT_DIR}/reports"
    
    cat > "$report_file" << EOF
<!DOCTYPE html>
<html>
<head>
    <title>系统监控报告 - $(date +%Y-%m-%d)</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .header { background: #f4f4f4; padding: 10px; border-radius: 5px; }
        .section { margin: 20px 0; }
        .status-ok { color: green; }
        .status-warning { color: orange; }
        .status-error { color: red; }
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <div class="header">
        <h1>教案管理平台监控报告</h1>
        <p>生成时间: $(date)</p>
    </div>
    
    <div class="section">
        <h2>系统资源使用情况</h2>
        <table>
            <tr><th>项目</th><th>当前值</th><th>状态</th></tr>
EOF
    
    # 添加系统资源信息到报告
    local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//' | sed 's/[^0-9.]*//g')
    local memory_info=$(free | grep Mem)
    local total_memory=$(echo $memory_info | awk '{print $2}')
    local used_memory=$(echo $memory_info | awk '{print $3}')
    local memory_percent=$(( used_memory * 100 / total_memory ))
    local disk_usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
    
    echo "            <tr><td>CPU使用率</td><td>${cpu_usage}%</td><td class=\"status-ok\">正常</td></tr>" >> "$report_file"
    echo "            <tr><td>内存使用率</td><td>${memory_percent}%</td><td class=\"status-ok\">正常</td></tr>" >> "$report_file"
    echo "            <tr><td>磁盘使用率</td><td>${disk_usage}%</td><td class=\"status-ok\">正常</td></tr>" >> "$report_file"
    
    cat >> "$report_file" << EOF
        </table>
    </div>
    
    <div class="section">
        <h2>服务状态</h2>
        <ul>
EOF
    
    # 添加服务状态到报告
    local services=("mongodb" "redis" "backend" "frontend" "nginx")
    for service in "${services[@]}"; do
        local container_name="lesson-plan-${service}-prod"
        if docker ps --filter "name=${container_name}" --filter "status=running" | grep -q "$container_name"; then
            echo "            <li class=\"status-ok\">$service: 运行正常</li>" >> "$report_file"
        else
            echo "            <li class=\"status-error\">$service: 服务异常</li>" >> "$report_file"
        fi
    done
    
    cat >> "$report_file" << EOF
        </ul>
    </div>
</body>
</html>
EOF
    
    log_success "监控报告已生成: $report_file"
}

# 自动修复服务
auto_repair() {
    log_info "尝试自动修复服务..."
    
    # 重启异常的容器
    local services=("mongodb" "redis" "backend" "frontend" "nginx")
    
    for service in "${services[@]}"; do
        local container_name="lesson-plan-${service}-prod"
        
        if ! docker ps --filter "name=${container_name}" --filter "status=running" | grep -q "$container_name"; then
            log_warning "尝试重启 $service 服务..."
            
            docker-compose -f docker-compose.prod.yml restart "$service"
            
            # 等待服务启动
            sleep 30
            
            if docker ps --filter "name=${container_name}" --filter "status=running" | grep -q "$container_name"; then
                log_success "$service 服务重启成功"
            else
                log_error "$service 服务重启失败"
                send_alert "CRITICAL" "$service 服务自动修复失败"
            fi
        fi
    done
}

# 主监控函数
main() {
    cd "$PROJECT_DIR"
    
    log_info "开始系统监控检查..."
    
    # 加载环境变量
    load_env
    
    # 系统资源检查
    check_system_resources
    
    # Docker服务检查
    check_docker_services
    
    # 应用健康检查
    check_application_health
    
    # 日志错误检查
    check_application_logs
    
    # SSL证书检查
    check_ssl_certificates
    
    # 收集性能指标
    collect_performance_metrics
    
    # 尝试自动修复（如果有问题）
    if [ "$AUTO_REPAIR" = "true" ]; then
        auto_repair
    fi
    
    log_success "监控检查完成"
}

# 显示帮助
show_help() {
    echo "系统监控脚本"
    echo ""
    echo "用法: $0 [command] [options]"
    echo ""
    echo "命令:"
    echo "  monitor         执行完整监控检查 (默认)"
    echo "  report          生成监控报告"
    echo "  repair          尝试自动修复服务"
    echo "  metrics         只收集性能指标"
    echo "  help            显示此帮助信息"
    echo ""
    echo "选项:"
    echo "  --auto-repair   自动尝试修复问题"
}

# 主程序
case "${1:-monitor}" in
    monitor)
        if [ "$2" = "--auto-repair" ]; then
            export AUTO_REPAIR=true
        fi
        main
        ;;
    report)
        generate_report
        ;;
    repair)
        cd "$PROJECT_DIR"
        load_env
        auto_repair
        ;;
    metrics)
        cd "$PROJECT_DIR"
        collect_performance_metrics
        ;;
    help|--help|-h)
        show_help
        ;;
    *)
        log_error "未知命令: $1"
        show_help
        exit 1
        ;;
esac